package cn.iot.util;

import cn.iot.common.dto.ResultMsg;
import cn.iot.common.utils.SpringUtils;
import cn.iot.sys.entity.SysDevice;
import cn.iot.sys.entity.SysFaceRecord;
import cn.iot.sys.service.SysFaceRecordService;
import com.netsdk.demo.module.LoginModule;
import com.netsdk.lib.NetSDKLib;
import com.netsdk.lib.ToolKits;
import com.sun.jna.Pointer;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

public class FacialInfo {
    // 查找句柄
    private static NetSDKLib.LLong m_FindHandle = null;

    // 查询密令
    public static int nToken = 0;

    /**
     * 订阅
     * @return
     */
    public static ResultMsg subscribe(SysDevice sysDevice) {
        NetSDKLib netSDKLib = NetSDKLib.NETSDK_INSTANCE;
        //初始化sdk,登录门禁
        boolean flag = LoginModule.logout();
        LoginModule.init(null, null);
        netSDKLib.CLIENT_Init(null, null);
        NetSDKLib.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY inParam = new NetSDKLib.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY();//入参
//        String m_strIp = "192.168.1.198";
//        int m_nPort = 37777;
//        String m_strUser = "admin";
//        String m_strPassword = "Admin123456";
        String m_strIp = sysDevice.getIpAddress();
        int m_nPort = Integer.parseInt(sysDevice.getPort());
        String m_strUser = sysDevice.getUsername();
        String m_strPassword = sysDevice.getPassword();
        inParam.nPort = m_nPort;
        inParam.szIP = m_strIp.getBytes();
        inParam.szPassword = m_strPassword.getBytes();
        inParam.szUserName = m_strUser.getBytes();

        //出参
        NetSDKLib.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY outParam = new NetSDKLib.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY();
        NetSDKLib.NET_DEVICEINFO_Ex deviceinfo = new NetSDKLib.NET_DEVICEINFO_Ex();
        outParam.stuDeviceInfo = deviceinfo;
        NetSDKLib.LLong loginHandle = netSDKLib.CLIENT_LoginWithHighLevelSecurity(inParam, outParam);
        NetSDKLib.LLong m_hAttachHandle = netSDKLib.CLIENT_RealLoadPictureEx(loginHandle, -1, NetSDKLib.EVENT_IVS_ALL, 1, FacialInfo.fAnalyzerDataCB.getInstance(), null, null);
        if (m_hAttachHandle.longValue() != 0) {
            System.out.println("智能订阅成功.");
        } else {
            System.err.println("智能订阅失败." + netSDKLib.CLIENT_GetLastError());
            return new ResultMsg(500, "智能订阅失败", null);
        }
        return new ResultMsg(200, "智能订阅成功", null);
    }

    /**
     * 停止订阅
     * @param m_hAttachHandle 智能订阅句柄
     */
    public static void stopRealLoadPicture(NetSDKLib.LLong m_hAttachHandle) {
        if(m_hAttachHandle.longValue() != 0) {
            LoginModule.netsdk.CLIENT_StopLoadPic(m_hAttachHandle);
            m_hAttachHandle.setValue(0);
        }
    }

    /**
     * invoke回调
     */
    public static class fAnalyzerDataCB implements NetSDKLib.fAnalyzerDataCallBack {
        private BufferedImage snapBufferedImage = null;
        private BufferedImage idBufferedImage = null;

        private fAnalyzerDataCB(){

        }
        private static class  fAnalyzerDataCBHolder{
            private static final FacialInfo.fAnalyzerDataCB instance = new FacialInfo.fAnalyzerDataCB();
        }

        public static FacialInfo.fAnalyzerDataCB getInstance(){
            return FacialInfo.fAnalyzerDataCB.fAnalyzerDataCBHolder.instance;
        }

        @Override
        public int invoke(NetSDKLib.LLong lAnalyzerHandle, int dwAlarmType, Pointer pAlarmInfo, Pointer pBuffer,
                          int dwBufSize, Pointer dwUser, int nSequence, Pointer reserved) {
            System.out.println("dwAlarmType" + dwAlarmType);

            SysFaceRecord sysFaceRecord = new SysFaceRecord();
            SysFaceRecordService sysFaceRecordService = SpringUtils.getBean(SysFaceRecordService.class);

            File path = new File("./iot-vue/src/assets/faceInfo");
            if (path.exists()) {
                path.mkdir();
            }
            switch (dwAlarmType) {
                case NetSDKLib.EVENT_IVS_ACCESS_CTL: // 门禁事件
                {
                    NetSDKLib.DEV_EVENT_ACCESS_CTL_INFO msg = new NetSDKLib.DEV_EVENT_ACCESS_CTL_INFO();
                    ToolKits.GetPointerData(pAlarmInfo, msg);
                    System.out.println("事件名称:" + new String(msg.szName).trim());
                    if (msg.emEventType == 1) {
                        System.out.println("门禁事件类型: 进门!");
                        sysFaceRecord.setValidStatus(msg.emEventType);
                    } else if (msg.emEventType == 2) {
                        System.out.println("门禁事件类型:出门!");
                        sysFaceRecord.setValidStatus(msg.emEventType);
                    }
                    if (msg.bStatus == 1) {
                        System.out.println("刷卡结果:成功! ");
                        sysFaceRecord.setBStatus(msg.bStatus);
                    } else if (msg.bStatus == 0) {
                        System.out.println("刷卡结果:失败! ");
                        sysFaceRecord.setBStatus(msg.bStatus);
                    }
                    System.out.println("卡类型: " + msg.emCardType);
                    System.out.println("开门方式: " + msg.emOpenMethod);
                    System.out.println("卡号 :" + new String(msg.szCardNo).trim());
                    System.out.println("开门用户:" + new String(msg.szUserID).trim());
                    System.out.println("开门失败原因错误码: " + msg.nErrorCode);
                    sysFaceRecord.setFailCode(msg.nErrorCode);
                    System.out.println("考勤状态: " + msg.emAttendanceState);
                    System.out.println("卡命名:" + new String(msg.szCardName).trim());
                    sysFaceRecord.setName(new String(msg.szCardName).trim());
                    System.out.println("相似度: " + msg.uSimilarity);
                    System.out.println("身份证号: " + new String(msg.szCitizenIDNo).trim());
                    System.out.println("当前事件是否为采集卡片: " + msg.emCardState);


                    System.out.println("szSN: " + new String(msg.szSN).trim());
                    String facePicPath = "";
                    String UUIDStr = UUID.randomUUID().toString();
                    facePicPath = path + "\\" + UUIDStr + "人脸图.jpg";
                    sysFaceRecord.setFaceImg(UUIDStr + "人脸图.jpg");
                    byte[] faceBuf = pBuffer.getByteArray(
                            msg.stuImageInfo[0].nOffSet,
                            msg.stuImageInfo[0].nLength);
                    ByteArrayInputStream byteArrInputFace = new ByteArrayInputStream(faceBuf);
                    try {
                        BufferedImage bufferedImage = ImageIO.read(byteArrInputFace);
                        if (bufferedImage != null) {
                            ImageIO.write(bufferedImage, "jpg", new File(facePicPath));
                            System.out.println("人脸图保存路径: " + facePicPath);
                        }
                    } catch (IOException e2) {
                        e2.printStackTrace();
                    }
                    break;
                }
                case NetSDKLib.EVENT_IVS_CITIZEN_PICTURE_COMPARE:   //人证比对事件
                {
                    NetSDKLib.DEV_EVENT_CITIZEN_PICTURE_COMPARE_INFO msg = new NetSDKLib.DEV_EVENT_CITIZEN_PICTURE_COMPARE_INFO();
                    ToolKits.GetPointerData(pAlarmInfo, msg);

                    try {
                        System.out.println("事件发生时间：" + msg.stuUTC.toString());
                        System.out.println("事件名称 :" + new String(msg.szName, "GBK").trim());

                        // 人证比对结果,相似度大于等于阈值认为比对成功, 1-表示成功, 0-表示失败
                        System.out.println("比对结果:" + msg.bCompareResult);

                        System.out.println("两张图片的相似度:" + msg.nSimilarity);
                        System.out.println("检测阈值:" + msg.nThreshold);

                        if (msg.emSex == 1) {
                            System.out.println("性别:男");
                        }else if (msg.emSex == 2){
                            System.out.println("性别:女");
                        }else {
                            System.out.println("性别:未知");
                        }
                        System.out.println("居民姓名:" + new String(msg.szCitizen, "GBK").trim());
                        System.out.println("住址:" + new String(msg.szAddress, "GBK").trim());
                        System.out.println("身份证号:" + new String(msg.szNumber).trim());
                        System.out.println("签发机关:" + new String(msg.szAuthority, "GBK").trim());

                        System.out.println("出生日期:" + msg.stuBirth.toStringTimeEx());
                        System.out.println("有效起始日期:" + msg.stuValidityStart.toStringTimeEx());
                        if (msg.bLongTimeValidFlag == 1) {
                            System.out.println("有效截止日期：永久");
                        }else{
                            System.out.println("有效截止日期:"+ msg.stuValidityEnd.toStringTimeEx());
                        }
                        System.out.println("IC卡号：" + new String(msg.szCardNo, "GBK").trim());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    // 拍摄照片
                    String strFileName = path + "\\" + System.currentTimeMillis() + "citizen_snap.jpg";
                    byte[] snapBuffer = pBuffer.getByteArray(msg.stuImageInfo[0].dwOffSet, msg.stuImageInfo[0].dwFileLenth);
                    ByteArrayInputStream snapArrayInputStream = new ByteArrayInputStream(snapBuffer);
                    try {
                        snapBufferedImage = ImageIO.read(snapArrayInputStream);
                        if(snapBufferedImage == null) {
                            return 0;
                        }
                        ImageIO.write(snapBufferedImage, "jpg", new File(strFileName));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    // 身份证照片
                    strFileName = path + "\\" + System.currentTimeMillis() + "citizen_id.jpg";
                    byte[] idBuffer = pBuffer.getByteArray(msg.stuImageInfo[1].dwOffSet, msg.stuImageInfo[1].dwFileLenth);
                    ByteArrayInputStream idArrayInputStream = new ByteArrayInputStream(idBuffer);
                    try {
                        idBufferedImage = ImageIO.read(idArrayInputStream);
                        if(idBufferedImage == null) {
                            return 0;
                        }
                        ImageIO.write(idBufferedImage, "jpg", new File(strFileName));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    break;
                }
                case NetSDKLib.EVENT_IVS_FACEDETECT: {        // 人脸检测事件
                    NetSDKLib.DEV_EVENT_FACEDETECT_INFO msg = new NetSDKLib.DEV_EVENT_FACEDETECT_INFO();
                    ToolKits.GetPointerData(pAlarmInfo, msg);

                    //System.out.println("人的运动速度 :" + msg.stuObject.Speed);
                }
                default:
                    break;
            }
            sysFaceRecordService.addFaceRecord(sysFaceRecord);
            return 0;
        }
    }

}
